/*
Script: dks_compact_accessible_forms.js
	Mootools plugin to create compact, accessible forms. 

License:
	MIT license.

Copyright:
	copyright (c) 2007 Philip Allard, <http://www.bossanoza.net/>.

Credits:
	- Based on the A List Apart article <http://www.alistapart.com/articles/makingcompactformsmoreaccessible/>.
	
Note:
	CompactAccessibleForms requires Mootools <http://www.mootools.net>.
*/

var DKS = {};

/*
Class: CompactAccessibleForms
	The CompactAccessibleForms plugin allows you to create compact, accessible forms. Meaning, it'll place the label tag paired with
	the input ouverlaying the textbox, making it disapear once the user sets focus on the textbox.
	
Note:
	CompactAccessibleForms requires Mootools <http://www.mootools.net>.

Arguments:
	els - required, [element id (string) | selector (string) | mootools element | mootools elements array] the parent(s) element(s) (most prolly a form).
	options - optional, see options below.

Options:
	targetLabelClassName - string, CSS class name that identify labels that need to be processed. defaults to "compactTarget".
	visibleLabelClassName - string, CSS class name of the label to be setted when the label is shown. defaults to "compactVisible".
	hiddenLabelClassName - string, CSS class name of the label to be setted when the label is hidden. defaults to "compactHidden".
	updateInputClass - boolean, if true, the input tag paired with the label tag will also have it's class updated. defaults to false.
	visibleInputClassName - string, CSS class name for the input paired with the label. defaults to null which defaults to visibleLabelClassName if updateInputClass is true.
	hiddenInputClassName - string, CSS class name for the input paired with the label. defaults to null which defaults to hiddenLabelClassName if updateInputClass is true.
*/

DKS.CompactAccessibleForms = new Class({
	options: {
		targetLabelClassName: "compactTarget",
		visibleLabelClassName: "compactVisible",
		hiddenLabelClassName: "compactHidden",
		updateInputClass: false,	
		visibleInputClassName: null,
		hiddenInputClassName: null
	},
	
	initialize: function(els, options){
		this.setOptions(options);
		
		// Setting defaults for input visible/hidden CSS class names
		this.options.visibleInputClassName = this.options.visibleInputClassName || this.options.visibleLabelClassName;
		this.options.hiddenInputClassName =  this.options.hiddenInputClassName || this.options.hiddenLabelClassName;
		
		if ($type(els) == 'array') { 
			els.each(function(el){ this.attachEvents(el); }.bind(this));			
		} else if ($type($(els)) == 'element') {			
			this.attachEvents($(els));
		} else { return; };
	},//end initialize
	
	attachEvents: function(container){
		// Set focus and blur handlers to hide and show LABELs with options.targetClassName class names
		var labels = container.getElements('label.' + this.options.targetLabelClassName);
		labels.each(function(el){								 
			// Skip labels that do not have a named association with another field.
			if (input = $(el.getProperty('for'))) {		
				// Setting initialized class names to hidden and attaching class initialization (visible/hidded according to
				// input data) on domReady event. This fixes two problems (a) IE:  pre-populated data will only be readable
			  // once the dom is ready, thus, if data is pre-populated the label would overlay pre-populated data of 
				// the textbox since input. (b) Firefox Password field pre-population seems to be readable only onDomReady 
				// (which defers from pre-populated fields via the value attribute), thus, overlapping occured.
				el.switchClass(this.options.targetLabelClassName, this.options.hiddenLabelClassName);
				window.addEvent('domready', this.setInitializeElementsClass.pass([el, input], this));
				
				// Set handlers to show and hide labels.
				input.addEvents({
					focus: function(event){this.onFocusChanged(event, el);}.bind(this),
					blur: function(event){this.onFocusChanged(event, el);}.bind(this)
				});
				
				// Handle clicks to LABEL elements (for Safari).
				el.addEvent('click', function(){this.focus;}.bind(input));
			};
		}.bind(this));
	},//end attachEvents
	
	setInitializeElementsClass: function(label, input){
		// Adding class to input (optional, but both needs to be defined...)
		if (this.options.updateInputClass) {					
			input.addClass((input.value == '') ? this.options.visibleInputClassName: this.options.hiddenInputClassName);
		};
		
		label.switchClass(this.options.hiddenLabelClassName, (input.value == '') ? this.options.visibleLabelClassName: this.options.hiddenLabelClassName);				
	},//end setInitializeElementsClass
	
	onFocusChanged: function(event, label){
		var event = new Event(event);
		this.toggleVisibility((event.type == 'focus' || event.target.value != ''), label, event.target);
	},//end onFocusChanged
	
	toggleVisibility: function(hide, label, input) {
		// Updating label class
		this.switchElementClass(label, hide, this.options.visibleLabelClassName, this.options.hiddenLabelClassName);

		// Updating input class
		if (this.options.updateInputClass) {
			this.switchElementClass(input, hide, this.options.visibleInputClassName, this.options.hiddenInputClassName);
		};
	},//end toggleVisibility
	
	switchElementClass: function(el, hide, visibleClassName, hiddenClassname){
		var addClassName = hide ? hiddenClassname: visibleClassName;
		var remClassName = hide ? visibleClassName: hiddenClassname;
		el.switchClass(remClassName, addClassName);
	}//end toggleClass
});

DKS.CompactAccessibleForms.implement(new Options);

Element.extend({
	switchClass: function(targetClassName, switchWithClassName){
		if(this.hasClass(targetClassName)) {this.removeClass(targetClassName);};
		if(!this.hasClass(switchWithClassName)) {this.addClass(switchWithClassName);};
	}
});